前言
javascript是单线程模型,如果要处理一些密集型任务时可能会拖慢主进程的执行(如页面UI卡顿),是否可以使javascript像其他语言使用多线程方式运行,一部分运行在UI线程下,另一部分运行一个独立线程(如只进行某些复杂运算)。
Web Worker作用就是为javascript提供一个创建多线程环境,但是这是浏览器的功能,实际和javascript语言本身几乎没什么关系,浏览器可以提供多个引擎实例,各自运行在自身的线程上,这样就可以在不同的线程上运行不同的程序。在worker内部是无法访问主程序的任何资源,这意味着你不能访问它的任何全局变量,也不能访问页面的DOM或者其他资源,这是一个完全独立的线程。
Web Worker 有以下几个使用注意点。
(1)同源限制
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(2)DOM 限制
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
(3)通信联系
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
(4)脚本限制
Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
(5)文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
用法
Worker之间以及他们主程序之间,不会共享任何作用域或资源,它是通过一个基本的事件消息机制相互联系。
1 |
|
具体使用详情可参考:Web Worker 使用教程
应用场景
Web Worker通常应用于哪些方面?
- 处理密集型数学计算
- 大数据集排序
- 数据处理(压缩、音频分析、图像处理等)
- 高流量网络通信
实战
当对一个文件需要生成MD5时,一般都是将文件传给后台然后将结果传递给前台进行使用,是否可以在前台直接生成然后使用呢?答案是肯定的,但是在未使用Web Worker时可能会影响页面响应,导致较大的文件不太使用此方法,但是我们可以用这个想法尝试使用一下Web Worker。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
const file = files[0]; // 获取文件对象
const fileReader = new FileReader();
const worker = new Worker('readFileAsBuffer.js') // 开启worker线
/*fileReader读取完成,传递给worker*/
fileReader.onload = function(e){
worker.postMessage({
operation:'sendArrayBuffer',
input:e.target.result,
threshold:0.8,
finish:true
},[e.target.result])
}
fileReader.onerror = function(){
console.log('文件读取失败,请重试');
}
/*worker线程计算MD5完成并返回结果*/
worker.onmessage = function(event){
/*读取完成,获取md5*/
const md5 = event.data;
file.md5 = md5;
}
/*使用FileReader读取文件*/
fileReader.readAsArrayBuffer(blobSlice.call(file,0,file.size));
//-----woker文件部分,readFileAsBuffer.js-------
/*在worker线程中,如果需要引入别的文件,要使用importScripts*/
importScripts('@/node_modules/spark-md5/spark-md5.js');
const spark = new SparkMD5.ArrayBuffer();
const saveArrayBuffer = [];
const start = false;
const finish = false;
/*接收到主线程发来的文件*/
onmessage = function(event){
spark.append(event.data.input);
const md5 = spark.end();
postMessage(md5);
}
目前对于Web Worker用得还比较少,也希望以后能看到全面且深度利用Web Worker的有意思的开源框架或项目。